package com.example.commonUpAndDownFileutil.util;
import com.example.commonUpAndDownFileutil.model.CommonResult;

import java.io.*;
import java.nio.file.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ZipUtil {
    /**
     * 解压ZIP文件（支持字符串路径输入）
     * @param zipFilePath ZIP文件的完整路径
     * @param targetDirPath 解压目标目录路径
     * @throws IOException 解压过程中发生的IO异常
     */
    public static void basicUnZip(String zipFilePath, String targetDirPath) throws IOException {
        // 1. 参数校验
        validateInputParams(zipFilePath, targetDirPath);

        // 2. 解析ZIP文件并校验存在性
        File zipFile = resolveAndValidateZipFile(zipFilePath);

        // 3. 处理目标目录
        Path targetDirPathObj = resolveAndCreateTargetDir(targetDirPath);

        // 4. 核心解压逻辑
        try (ZipInputStream zis = new ZipInputStream(
                new BufferedInputStream(new FileInputStream(zipFile)),
                java.nio.charset.Charset.forName("GBK")  // 新增：指定支持中文的编码
        )) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                Path entryPath = targetDirPathObj.resolve(entry.getName());

                // 路径越界检查
                checkPathTraversal(targetDirPathObj, entryPath, entry.getName());

                if (entry.isDirectory()) {
                    Files.createDirectories(entryPath);
                } else {
                    Files.createDirectories(entryPath.getParent());
                    try (BufferedOutputStream bos = new BufferedOutputStream(
                            Files.newOutputStream(entryPath,
                                    StandardOpenOption.CREATE,
                                    StandardOpenOption.TRUNCATE_EXISTING)
                    )) {
                        byte[] buffer = new byte[8192];
                        int bytesRead;
                        while ((bytesRead = zis.read(buffer)) != -1) {
                            bos.write(buffer, 0, bytesRead);
                        }
                    }
                }
                zis.closeEntry();
            }
        }
    }

    private static boolean containsChinese(String str) {
        if (str == null) {
            return false;
        }
        // 遍历字符，检查是否包含中文（Unicode范围：\u4e00-\u9fa5）
        for (char c : str.toCharArray()) {
            if (c >= '\u4e00' && c <= '\u9fa5') {
                return true;
            }
        }
        return false;
    }

    /**
     * 校验输入参数合法性
     */
    private static void validateInputParams(String zipFilePath, String targetDirPath) {
        if (zipFilePath == null || zipFilePath.trim().isEmpty()) {
            throw new IllegalArgumentException("ZIP文件路径不能为空");
        }
        if (targetDirPath == null || targetDirPath.trim().isEmpty()) {
            throw new IllegalArgumentException("目标目录路径不能为空");
        }
        // 新增：检查ZIP文件名是否包含中文
        if (containsChinese(zipFilePath)) {
            throw new IllegalArgumentException("ZIP文件路径包含中文，可能导致解压异常：" + zipFilePath);
        }

        // 新增：检查目标目录是否包含中文
        if (containsChinese(targetDirPath)) {
            throw new IllegalArgumentException("目标目录路径包含中文，可能导致解压异常：" + targetDirPath);
        }
    }

    /**
     * 解析ZIP文件路径并校验文件存在性
     */
    private static File resolveAndValidateZipFile(String zipFilePath) throws FileNotFoundException {
        File zipFile = new File(zipFilePath);
        if (!zipFile.exists()) {
            throw new FileNotFoundException("ZIP文件不存在：" + zipFile.getAbsolutePath());
        }
        if (!zipFile.isFile()) {
            throw new FileNotFoundException("指定路径不是有效文件：" + zipFile.getAbsolutePath());
        }
        return zipFile;
    }

    /**
     * 解析目标目录路径并创建（若不存在）
     */
    private static Path resolveAndCreateTargetDir(String targetDirPath) throws IOException {
        Path targetDir = Paths.get(targetDirPath);
        Files.createDirectories(targetDir); // 递归创建所有不存在的父目录
        return targetDir;
    }

    /**
     * 检查路径是否越界（防御ZipSlip攻击）
     */
    private static void checkPathTraversal(Path targetDir, Path entryPath, String entryName) throws IOException {
        // 规范化路径后检查是否在目标目录内
        if (!entryPath.normalize().startsWith(targetDir.normalize())) {
            throw new IOException("检测到恶意压缩条目（路径越界）：" + entryName);
        }
    }

}
